// 校验是否为 Android 环境
export const isAndroid = () => {
  return /(Android|Adr)/i.test(navigator.userAgent)
}

// 校验是否为 IOS 环境
export const isIOS = () => {
  return /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)
}

// 校验字符串：只能是英文字母和下划线
export const isAlphaAndUnderline = (str: string) => {
  if (typeof str !== 'string') throw new Error(`arguments[0] is required string but got ${str}`)

  return /^[a-z-A-Z_]+$/.test(str)
}

// 校验是否为合法URL
export const isURL = (url: string) => {
  if (typeof url !== 'string') throw new Error(`arguments[0] is required string but got ${url}`)

  const regs =
    '^((https?|ftp):)?(//)?' + // 匹配以http、https或ftp开头的URL
    '(([^:@]+:[^:@]+@)?' + // 匹配可选的用户名和密码，格式为username:password@，这部分是可选的
    '(([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // 匹配域名
    '((\\d{1,3}\\.){3}\\d{1,3})|' + // OR 匹配IPv4地址
    '(\\[[0-9a-f:]{3,40}\\])|' + // OR 匹配IPv6地址
    '(localhost))' + // OR 匹配localhost
    '(\\:\\d+)?' + // 匹配端口号，格式为:port。这部分是可选的
    "(\\/($|[a-zA-Z0-9\\u4e00-\\u9fa5.,?'\\\\+&%$#=~_-]+))*$" // 匹配URL的路径部分，可以包含多个路径段，每个路径段以/开始

  const reg = new RegExp(regs, 'i')

  return reg.test(url)
}

export declare type IsIpAddress = {
  (ip: string): boolean
  (ip: string, type: 'IPv4'): boolean
  (ip: string, type: 'IPv6'): boolean
}

// 校验是否为正确的IP地址
export const isIpAddress: IsIpAddress = (ip: string, type?: 'IPv4' | 'IPv6') => {
  if (typeof ip !== 'string') throw new Error(`arguments[0] is required string but got ${ip}`)

  const regIPv4 = '^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'

  const regIPv6 =
    '^([0-9a-fA-F]{1,4}:){7}([0-9a-fA-F]{1,4}|:)$|^::(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4}$|^([0-9a-fA-F]{1,4}:){1,6}:$|^([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}$|^([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}$|^([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}$|^([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}$|^[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})$|^:((:[0-9a-fA-F]{1,4}){1,7}|:)$|^fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}$|^::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])$|^([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])$'

  const regs: string[] = []

  switch (type) {
    case 'IPv4':
      regs.push(regIPv4)
    case 'IPv6':
      regs.push(regIPv6)
      break
    default:
      regs.push(regIPv4, regIPv6)
      break
  }

  const reg = new RegExp(regs.join('|'))

  return reg.test(ip)
}

// 校验是否为银行卡号
export const isBankCardCode = (code: string) => {
  if (typeof code !== 'string') throw new Error(`arguments[0] is required string but got ${code}`)

  // 银行卡号正则
  const regs = [
    '^(62|18|19|20|21|22|23|24|25|26|27|30|31|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|58|60|65|84|87|88|89|94|95|96|97|98|99)\\d{14,17}$', // 中国大陆地区银行卡号
    '^3[47]\\d{13}$', // 美国运通卡
    '^4\\d{12}(\\d{3})?$', // Visa卡
    '^5[1-5]\\d{14}$', // MasterCard卡
    '^6(?:011|5\\d{2})\\d{12}$', // Discover卡
    '^(?:2131|1800|35\\d{3})\\d{11}$', // JCB卡
    '^65[2-9]d{12}|650[0-9]d{11}|6511d{12}|3[4-9]d{15}$' // RuPay卡
  ]

  const reg = new RegExp(regs.join('|'))

  return reg.test(code)
}

// 校验运单号是否正确
export const isBillCode = (code: string) => {
  if (typeof code !== 'string') throw new Error(`arguments[0] is required string but got ${code}`)

  const reg = new RegExp(
    '^((768|765|778|779|719|518|880|660|805|718|728|738|761|762|763|701|757|689|738|528)[0-9]{9})$|^2013[0-9]{8}$|^((8010|8021)[0-9]{6})$|^((a|b|h)[0-9]{13})$|^((5)[0-9]{9})$|^((80|88|89|90|91|92|93|94|95|96|97|99|200|21)[0-9]{8})$|^(90|91|94|53)[0-9]{10}$|^(120)[0-9]{9}$|^(23)[0-9]{8}$|^(780)[0-9]{9}$|^(881)[0-9]{9}$|^(6666666666)[0-9]{2}$|^54[0-9]{10}$|^(24)[0-9]{8}$|^(960)[0-9]{9}$|^665[0-9]{9}$|^(wx|hf)[0-9]{10}$|^(25)[0-9]{8}$|^(26)[0-9]{8}$|^(63|64)[0-9]{10}$|^(72)[0-9]{10}$|^(220|221|223|224|225|226|227|228|229)[0-9]{7}$|^3[0-9]{9}$|^731[0-9]{11}$|^73220[0-9]{9}$|^73200[0-9]{9}$|^7518[0-9]{8}$|^4[0-9]{9}$|^73210[0-9]{9}$|^771[0-9]{11}$|^733000[0-9]{8}$|^73211[0-9]{9}$|^5[0-9]{9}$|^(A)[0-9]{9}$|^C[0-9]{9}$|^D[0-9]{9}$|^781[0-9]{11}$|^(7)[0-9]{9}$|^73222[0-9]{9}$|^734[0-9]{11}$|^75210[0-9]{9}$|^73223[0-9]{9}$|^73224[0-9]{9}$|^8[0-9]{7}$|^100[0-9]{9}$|^118[0-9]{9}$|^128[0-9]{9}$|^688[0-9]{9}$|^68[0-9]{10}$|^882[0-9]{9}$|^9[0-9]{7}$|^010[0-9]{9}$|^628[0-9]{9}$|^E[0-9]{9}$|^F[0-9]{9}$|^G[0-9]{9}$|^H[0-9]{9}$|^7777[0-9]{10}$|^758[0-9]{11}$|^759[0-9]{11}$|^760[0-9]{11}$|^741[0-9]{11}$|^73226[0-9]{9}$|^777600[0-9]{8}$|^77761[0-9]{9}$|^73227[0-9]{9}$|^H[0-9]{9}$|^J[0-9]{9}$|^K[0-9]{9}$|^L[0-9]{9}$|^M[0-9]{9}$|^N[0-9]{9}$|^73225[0-9]{9}$|^31111[0-9]{9}$|^754[0-9]{11}$|^O[0-9]{9}$|^P[0-9]{9}$|^Q[0-9]{9}$|^R[0-9]{9}$|^S[0-9]{9}$|^T[0-9]{9}$|^755[0-9]{11}$|^73228[0-9]{9}$|^73229[0-9]{9}$|^782[0-9]{11}$|^756[0-9]{11}$|^U[0-9]{9}$|^V[0-9]{9}$|^W[0-9]{9}$|^X[0-9]{9}$|^Y[0-9]{9}$|^Z[0-9]{9}$|^[A-Z]{2}[0-9]{8}$|^766[0-9]{11}$',
  )

  return reg.test(code)
}

// 校验是否为车签号
export const isCarSignCode = (code: string) => {
  if (typeof code !== 'string') throw new Error(`arguments[0] is required string but got ${code}`)

  return /^[0-9a-zA-Z]+(,?[0-9a-zA-Z])*$/.test(code)
}

// 校验是否为驾驶证号码
export const isDrivingLicenseCode = (code: string) => {
  if (typeof code !== 'string') throw new Error(`arguments[0] is required string but got ${code}`)

  return /(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)/.test(code)
}

// 校验是否为邮箱
export const isEmail = (email: string) => {
  if (typeof email !== 'string') throw new Error(`arguments[0] is required string but got ${email}`)

  const reg = new RegExp(`^(([^<>()[\\]\\\\.,;:\\s@"]+(\\.[^<>()[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$`)

  return reg.test(email)
}

// 校验是否车牌号
export const isLicensePlateNumber = (NO: string) => {
  if (typeof NO !== 'string') throw new Error(`arguments[0] is required string but got ${NO}`)

  let regs = [
    '^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使][A-Z]([0-9a-zA-Z]{4}[挂超警学领港澳0-9a-zA-Z]|[DF][0-9a-zA-Z]{5}|[0-9a-zA-Z]{5}[DF])$',
    '^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使][A-Z]([0-9a-zA-Z]{4}[警学领港澳0-9a-zA-Z]|[DF][0-9a-zA-Z]{5}|[0-9a-zA-Z]{5}[DF])$',
    '^WJ[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新]?[0-9a-zA-Z]{5}$', // 武警车
    '^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新][A-Z][0-9a-zA-Z]{4}[挂超]{1}$' // 车挂
  ]

  const reg = new RegExp(regs.join('|'))

  return reg.test(NO)
}

// 校验是否为手机号
export const isMobile = (mobile: string) => {
  if (typeof mobile !== 'string') throw new Error(`arguments[0] is required string but got ${mobile}`)

  const regs = [
    '^1[3-9]\\d{9}$',
    '^(1[3-5]\\d|1[8-9]\\d|16[^257]|17[^01])\\d{8}$',
    '^(13\\d|14[^1-4|8]|15[^4]|16[2|5-7]|17[^4|9]|18\\d|19[^0|2|4])\\d{8}$',
    '^(13\\d|14[^1-4|8]|15[^4]|166|17[^0|1|4|9]|18\\d|19[^0|2|4])\\d{8}$'
  ]

  const reg = new RegExp(regs.join('|'))

  return reg.test(mobile)
}

// 校验是否为固定电话号码
export const isTel = (tel: string) => {
  if (typeof tel !== 'string') throw new Error(`arguments[0] is required string but got ${tel}`)

  return /^(0\\d{2,3}-)?\\d{7,8}(-\\d{1,6})?$/.test(tel)
}

// 校验是否为电话号码, 包括手机和固话
export const isPhone = (phone: string) => {
  if (typeof phone !== 'string') throw new Error(`arguments[0] is required string but got ${phone}`)

  return isMobile(phone) || isTel(phone)
}
